#ifndef HARDWAREABSTRACTIONINTERACTIONPROTOCOLLAYER_H
#define HARDWAREABSTRACTIONINTERACTIONPROTOCOLLAYER_H


#include "EventAggregator.h"
#include "Direction.h"
#include <Arduino.h>
#include "StationaryWashingDevice.h"
class StationaryWashingDevice;
#include "AtomicAtomShakingDeviceController.h"

//these classes are put here to avoid a cyclic dependency.
class HeavyDutySuperCollidingSuperButtonDeviceController;
class MonetaryValuedCircularMetalObjectDeviceController;
class HydrofobicAntiStainCompartiment;
class LiquidDistributionChannelingDeviceController;
class UserInteractionGateDeviceController;



#include "IWaterHAL.h"
#include "IMotorHAL.h"
#include "IDoorHAL.h"
#include "IHeaterHAL.h"
#include "IMoneyHAL.h"
#include "IButtonHAL.h"
#include "ISoapHAL.h"
#include "Arduino.h"
#include "TimerOne.h"
#include "HALMode.h"

class HardwareAbstractionInteractionProtocolLayer : public IWaterHAL, public IMotorHAL, public IDoorHAL, public IHeaterHAL, public IMoneyHAL, public IButtonHAL, public ISoapHAL
{
    public:
        HardwareAbstractionInteractionProtocolLayer();
        virtual ~HardwareAbstractionInteractionProtocolLayer();
        void initialize();
        static HardwareAbstractionInteractionProtocolLayer *instance;


        //EventAggregator *on10CentsEntered;
        //EventAggregator *on50CentsEntered;
        //EventAggregator *on200CentsEntered;
        //EventAggregator *onClear;


        //buttons
        //EventAggregator *onProgramSelectPressed;
        //TODO: programs leds; to be fixed or not to be fixed.
        //EventAggregator *onStartPressed;

        //soap
        void tray1FlushSoapIntoASSWD();
        void tray2FlushSoapIntoASSWD();
        //EventAggregator *onTray1Filled;
		//EventAggregator *onTray2Filled;

        //heater
		virtual int getTemperature();
		void setTemperature(int temp);
		bool getIsCorrectTemp();
		//EventAggregator *onIsCorrectTemp;

        //water
		void openDrain();
		void closeDrain();
		void openSink();
		void closeSink();
		void registerWantedWaterLevel(int level);
		int getWaterLevel();
		bool getIsWaterAtRegisteredLevel();

		//EventAggregator *onWaterLevelAtRegisteredLevel;
		//EventAggregator *onWaterPressureHigh; //INTERRUPT!
        //EventAggregator *onWaterPressureLow; //INTERRUPT!

        //door
        //EventAggregator *onDoorClosed;
        //EventAggregator *onDoorOpened;
		void lockDoor();
		void unlockDoor();

        //motor
        void setMotorSpeed(int speed);
        void setMotorDirection(Direction dir);
		
		void ignoreTheDIP(HeavyDutySuperCollidingSuperButtonDeviceController *buttons,UserInteractionGateDeviceController *door,AtomicAtomShakingDeviceController *heater,MonetaryValuedCircularMetalObjectDeviceController *money,HydrofobicAntiStainCompartiment *soap1, HydrofobicAntiStainCompartiment *soap2, StationaryWashingDevice *wash,LiquidDistributionChannelingDeviceController *water);

        void loopISR();

    protected:
    private:
		bool isCorrectTemp;
        int correctHeat;
        int statusTray1;
        int statusTray2;
        int waterLevel;
        int waterPressure;
        int wantedWaterLevel;
        bool waterAlreadyAtRegisteredLevel;
        int wantedTemp;
        void resetPorts(void);
		bool flushSoapTray1, flushSoapTray2;

		

		HALMode mode;

        boolean waterPressureHigh;
        boolean soapTray1Filled, soapTray2Filled;
        boolean lastDoorClosed;
        boolean lastWaterPressureHigh;
        boolean lastValueForSoapTray1Filled,
        		lastValueForSoapTray2Filled;
        boolean startButtonListening, programButtonListening;
        int currentProg, preProg;
        boolean moneySlotOn10, moneySlotOn50, moneySlotOn200, the4thbuttonOn, reset, moneySlotListening;
        int amtOf10sEntered, amtOf50sEntered, amtOf200sEntered, preamtOf10sEntered, preamtOf50sEntered, preamtOf200sEntered;


		HeavyDutySuperCollidingSuperButtonDeviceController *weDontDoNoDIPButton;
		UserInteractionGateDeviceController *weDontDoNoDIPDoor;
		AtomicAtomShakingDeviceController *weDontDoNoDIPHeater;
		MonetaryValuedCircularMetalObjectDeviceController *weDontDoNoDIPMoney;
		HydrofobicAntiStainCompartiment *weDontDoNoDIPSoap1;
		HydrofobicAntiStainCompartiment *weDontDoNoDIPSoap2;
		StationaryWashingDevice *weDontDoNoDIPWash;
		LiquidDistributionChannelingDeviceController *weDontDoNoDIPWater;

};

#endif // HARDWAREABSTRACTIONINTERACTIONPROTOCOLLAYER_H
